package com.hiultra.archive.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSON;
import com.hiultra.archive.controller.print.javagodex.demos.web.GodexPrinter;
import com.hiultra.archive.device.print.PrintManager;
import com.hiultra.archive.device.shelve.ShelvesManager;
import com.hiultra.archive.domain.ArcBox;
import com.hiultra.archive.domain.ArchiveArchArea;
import com.hiultra.archive.domain.ArchiveCabinet;
import com.hiultra.archive.domain.vo.ArcBoxVo;
import com.hiultra.archive.domain.vo.ResultEntity;
import com.hiultra.archive.mapper.*;
import com.hiultra.archive.service.IArcBoxService;
import com.hiultra.archive.utils.sgsm.SM2Util;
import com.hiultra.archive.utils.tool.ToolUtils;
import com.hiultra.common.constant.BusinessConstants;
import com.hiultra.common.constant.UserConstants;
import com.hiultra.common.exception.ServiceException;
import com.hiultra.common.utils.ArcUtil;
import com.hiultra.common.utils.StringUtils;
import com.hiultra.common.utils.bean.BeanValidators;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.Validator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 档案盒管理Service业务层处理
 *
 * @author ls
 * @date 2022-07-28
 */
@Service
public class ArcBoxServiceImpl implements IArcBoxService {
    private static final Logger log = LoggerFactory.getLogger(ArcDossierServiceImpl.class);
    @Autowired
    protected Validator validator;
    @Autowired
    private ArcBoxMapper arcBoxMapper;
    @Autowired
    private ArcCabinetMapper arcCabinetMapper;
    @Autowired
    private ArcShelvesMapper arcShelvesMapper;
    @Value("${roomNo}")
    private String roomNo;
    @Value("${priKey}")
    private String priKey;
    @Autowired
    private ArchiveCabinetMapper archiveCabinetMapper;
    @Autowired
    private ArchiveArchAreaMapper archiveArchAreaMapper;
    @Autowired
    ShelvesManager shelvesManager;
    //样式集合 括号内添加即可
    List<String> styleNumberList = new ArrayList<String>(Arrays.asList("15", "40"));

    //创建打印机对象
    GodexPrinter godexPrinter = new GodexPrinter();

    /**
     * 查询档案盒管理
     *
     * @param boxId 档案盒管理主键
     * @return 档案盒管理
     */
    @Override
    public ArcBox selectArcBoxByBoxId(String boxId) {
        return arcBoxMapper.selectArcBoxByBoxId(boxId);
    }

    /**
     * 查询档案盒根据rfid
     *
     * @param boxRfids 档案盒管理主键
     * @return 档案盒管理
     */
    @Override
    public List<ArcBox> selectArcBoxListByRfid(List<String> boxRfids) {
        return arcBoxMapper.selectArcBoxListByRfid(boxRfids);
    }

    /**
     * 查询档案盒管理列表
     *
     * @param arcBox 档案盒管理
     * @return 档案盒管理
     */
    @Override
    public List<ArcBox> selectArcBoxList(ArcBox arcBox) {
        return arcBoxMapper.selectArcBoxList(arcBox);
    }

    /**
     * 新增档案盒管理
     *
     * @param arcBox 档案盒管理
     * @return 结果
     */
    @Override
    public int insertArcBox(ArcBox arcBox) {
        return arcBoxMapper.insertArcBox(arcBox);
    }

    /**
     * 修改档案盒管理
     *
     * @param arcBox 档案盒管理
     * @return 结果
     */
    @Override
    public int updateArcBox(ArcBox arcBox) {

        return arcBoxMapper.updateArcBox(arcBox);
    }

    /**
     * 批量删除档案盒管理
     *
     * @param boxIds 需要删除的档案盒管理主键
     * @return 结果
     */
    @Override
    public int deleteArcBoxByBoxIds(String[] boxIds) {
        return arcBoxMapper.deleteArcBoxByBoxIds(boxIds);
    }

    /**
     * 删除档案盒管理信息
     *
     * @param boxId 档案盒管理主键
     * @return 结果
     */
    @Override
    public int deleteArcBoxByBoxId(String boxId) {
        return arcBoxMapper.deleteArcBoxByBoxId(boxId);
    }

    /**
     * 导入档案盒数据
     *
     * @param boxList         档案盒数据列表
     * @param isUpdateSupport 是否更新支持，如果已存在，则进行更新数据
     * @param operName        操作用户
     * @return 结果
     */
    @Override
    @Transactional
    public String importBox(List<ArcBox> boxList, Boolean isUpdateSupport, String operName) {
        if (StringUtils.isNull(boxList) || boxList.size() == 0) {
            throw new ServiceException("导入档案盒数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for (ArcBox box : boxList) {
            try {
                // 验证是否存在档案盒信息
                ArcBox b = arcBoxMapper.selectArcBoxByBoxCode(box.getBoxCode());
                if (StringUtils.isNull(b)) {
                    BeanValidators.validateWithException(validator, box);
                    box.setCreateBy(operName);
                    this.insertArcBox(box);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、档案盒 " + box.getBoxCode() + " 导入成功");
                } else if (isUpdateSupport) {
                    BeanValidators.validateWithException(validator, box);
                    box.setUpdateBy(operName);
                    this.updateArcBox(box);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、档案盒 " + box.getBoxCode() + " 更新成功");
                } else {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、档案盒 " + box.getBoxCode() + " 已存在");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、档案盒 " + box.getBoxCode() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    /**
     * 校验档案盒号称是否唯一
     *
     * @param arcBox 档案盒
     * @return 结果
     */
    @Override
    public String checkBoxCodeUnique(ArcBox arcBox) {
        String boxId = StringUtils.isNull(arcBox.getBoxId()) ? "" : arcBox.getBoxId();
        ArcBox info = arcBoxMapper.checkBoxCodeUnique(arcBox);
        if (StringUtils.isNotNull(info) && !info.getBoxId().equals(boxId)) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 批量打印标签
     *
     * @param boxIds 档案盒主键集合
     * @return 结果
     */
    @Override
    public List<ArcBox> batchPrint(String[] boxIds) {

        List<ArcBox> arcBoxList = new ArrayList<>(boxIds.length);
        for (String temps : boxIds) {
            ArcBox entity = arcBoxMapper.selectArcBoxByBoxId(temps);
            String rfidNum = ArcUtil.getOrderNoTo12();
            entity.setRfid(rfidNum);

            ArcBox entityUpdate = new ArcBox();
            entityUpdate.setBoxId(entity.getBoxId());
            entityUpdate.setRfid(entity.getRfid());
            arcBoxMapper.updateArcBox(entityUpdate);

            arcBoxList.add(entity);
        }

        return arcBoxList;
    }

    /**
     * 修改档案盒位置
     *
     * @param arcBox 档案盒管理
     * @return 结果
     */
    @Override
    public int editPosition(ArcBox arcBox) {
//        //查询具体位置全名
//        String fullName = "";
//        //智能柜
//        if (BusinessConstants.LOCATION_TYPE_CABINET.equals(arcBox.getPositionType())) {
//            fullName = selectFullCabinetName(arcBox.getShelvesId(), new ArrayList<>());
//        } else if (BusinessConstants.LOCATION_TYPE_SHELVES.equals(arcBox.getPositionType())) {
//            fullName = selectFullShelvesName(arcBox.getShelvesId(), new ArrayList<>());
//        }
//        arcBox.setShelvesLayerGridName(fullName);
        return arcBoxMapper.updateArcBox(arcBox);
    }

    /**
     * 组合智能柜位置名
     */
    public String selectFullCabinetName(Long cainetId, List<String> str) {
        String name = "";
        // 根据code查名称,上级的名称
        List<Map<String, Object>> list = arcCabinetMapper.selectCabinetName(cainetId);
        String storehouseName = "";
        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> map = list.get(i);
            Long parentId = (Long) map.get("id");
            storehouseName = (String) map.get("name");
            str.add(storehouseName);
            if (0 != parentId) {
                selectFullCabinetName(parentId, str);
            }
            for (int z = str.size() - 1; z >= 0; z--) {// 倒序输出
                name += str.get(z) + "-";
            }
        }
        return name;
    }

    /**
     * 组合密集架位置名
     */
    public String selectFullShelvesName(Long shelvesId, List<String> str) {
        String name = "";
        // 根据code查名称,上级的名称
        List<Map<String, Object>> list = arcShelvesMapper.selectShelvesName(shelvesId);
        String storehouseName = "";
        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> map = list.get(i);
            Long parentId = (Long) map.get("id");
            storehouseName = (String) map.get("name");
            str.add(storehouseName);
            if (0 != parentId) {
                selectFullShelvesName(parentId, str);
            }
            for (int z = str.size() - 1; z >= 0; z--) {// 倒序输出
                name += str.get(z) + "-";
            }
        }
        return name;
    }

    /**
     * 批量新增档案盒管理
     *
     * @param arcBoxList 档案盒管理
     * @return 结果
     */
    @Override
    public int batchInsertArcBox(List<ArcBox> arcBoxList) {
        if (ObjectUtil.isEmpty(arcBoxList)) {
            return 0;
        }
        return arcBoxMapper.batchInsertArcBox(arcBoxList);
    }

    /**
     * 新增档案盒接口（省侧下发）
     *
     * @param data
     * @return 结果
     */
    @Override
    public ResultEntity insertIssuedArcBox(String data) {
        //解密
        System.out.println("新增档案盒任务入参：" + data);
        String decryptedResult = new SM2Util().decryptBySM2(data, priKey);
        System.out.println("新增档案盒任务下发解密结果：" + decryptedResult);
        ArcBoxVo arcBoxVo = JSON.parseObject(decryptedResult.trim(), ArcBoxVo.class);
        if (ObjectUtil.isEmpty(arcBoxVo)) {
            log.info("入参解析失败，请检查入参！");
            return ResultEntity.error("入参解析失败，请检查重试！");
        }
        ArcBox arcBox = ToolUtils.convertEntity(arcBoxVo, ArcBox::new);

        ArchiveCabinet archiveCabinet = archiveCabinetMapper.selectArchiveCabinetById(arcBoxVo.getCabinetId());
        if (ObjectUtil.isEmpty(archiveCabinet)) {
            log.info("未找到此档案盒所属档案柜标识" + arcBoxVo.getCabinetId() + "信息，请检查重试！");
            return ResultEntity.error("未找到此档案盒所属档案柜标识" + arcBoxVo.getCabinetId() + "信息，请检查重试！");
        }

        arcBox.setCabinetNo(archiveCabinet.getColNo());
        arcBox.setBoxCode(arcBoxVo.getBoxNo());
        arcBox.setBoxRfid(arcBoxVo.getBoxBarCode());
        arcBox.setDelflag(0);
        //todo文档中是档案盒条码和rfid两个字段
        arcBox.setSpecs(arcBoxVo.getBoxSpec());
        arcBox.setBoxStatus(arcBoxVo.getBoxStat());
        arcBox.setBoxStatus(!arcBoxVo.getBoxStat().isEmpty() ? arcBoxVo.getBoxStat() : BusinessConstants.BOX_STAT_PRE);
        //设置保管期限默认值
        arcBox.setKeepDur(!arcBoxVo.getKeepDur().isEmpty() ? arcBoxVo.getKeepDur() : BusinessConstants.BOX_PERIOD_FOREVER);
        //设置保管级别默认值
        arcBox.setConfdLv(!arcBoxVo.getConfdLv().isEmpty() ? arcBoxVo.getConfdLv() : BusinessConstants.BOX_SECRET_PUBLIC);
        ArchiveArchArea archiveArchArea = archiveArchAreaMapper.selectArchiveArchAreaById(arcBoxVo.getAreaId());
        if (ObjectUtil.isEmpty(archiveArchArea)) {
            log.info("未找到此档案盒所属档案区标识" + arcBoxVo.getAreaId() + "信息，请检查重试！");
            return ResultEntity.error("未找到此档案盒所属档案区标识" + arcBoxVo.getAreaId() + "信息，请检查重试！");
        }
        arcBox.setAreaNo(archiveArchArea.getArchAreaNo());
        //设置默认值
        arcBox.setGiveBackStatus(BusinessConstants.PRE_GIVE_BACK_STATUS);
        arcBox.setStatus(BusinessConstants.PRE_IS_WRITE_CARD);

        //存在即修改，不存在即新增
        ArcBox arcBoxIsExist = arcBoxMapper.selectArcBoxByBoxId(arcBox.getBoxId());
        if (ObjectUtil.isNotEmpty(arcBoxIsExist)) {
            //修改
            arcBoxMapper.updateArcBox(arcBox);
        } else {
            arcBoxMapper.insertArcBox(arcBox);
        }
        return ResultEntity.success();
    }

    /**
     * 操作密集架
     *
     * @param arcBox 档案盒管理
     * @return 结果
     */
    @Override
    public int operationShelvesByBoxNo(ArcBox arcBox) {
        //根据id查档案盒信息
        ArcBox arcBoxById = arcBoxMapper.selectArcBoxByBoxId(arcBox.getBoxId());
        if (ObjectUtil.isEmpty(arcBoxById)) {
            throw new ServiceException("未查询到档案盒信息，请检查重试！");
        }
        //根据档案柜编号和档案区编号查询详细信息

        ArchiveArchArea archiveArchArea = archiveArchAreaMapper.selectArchiveArchAreaByArchAreaNo(arcBoxById.getAreaNo());
        //判空
        if (ObjectUtil.isEmpty(archiveArchArea)) {
            throw new ServiceException("未查询到档案盒所属档案柜信息，请检查重试！");
        }
        String ip = archiveArchArea.getCabinetIp();
        if (ObjectUtil.isEmpty(ip)) {
            throw new ServiceException("未查询到档案盒所属档案柜IP，请检查重试！");
        }
        //根据柜号查询档案柜信息
        ArchiveCabinet archiveCabinet = archiveCabinetMapper.selectArchiveCabinetByNo(new ArchiveCabinet() {{
            setColNo(arcBoxById.getCabinetNo());
            setArchiveAreaNo(arcBoxById.getAreaNo());
        }});
        if (ObjectUtil.isEmpty(archiveCabinet)) {
            throw new ServiceException("未查询到档案盒所属档案柜信息，请检查重试！");
        }
        //判断是否固定列
        if (archiveCabinet.getIsFixedCol().equals(BusinessConstants.IS_FIXED_COL)) {
            throw new ServiceException("此档案柜为固定列，无法操作！");

        }
        //判断是否运行开柜
        if (archiveCabinet.getIsOpen().equals(BusinessConstants.IS_NOT_OPEN)) {
            throw new ServiceException("此档案柜不允许开柜，无法操作！");
        }
        String warehouseCode = "01";
        String areaCode = archiveArchArea.getArchAreaNo();
        String columnNoS = arcBoxById.getCabinetNo();
        int colNo = Integer.parseInt(columnNoS);

        log.info("ip：" + ip + "  warehouseCode：" + warehouseCode + "  areaCode：" + areaCode + "  areaCode：" + areaCode + "  colNo：" + colNo);
        int columnNo = (colNo + 1) / 2;

//        sort  0 从左至右 1 从右至左
        int sort = 0;
        if (archiveCabinet.getOpenDirection().equals("right")) {
            sort = 0;
        } else {
            sort = 1;
        }
        String faceNo = "0";
        if ((colNo + 1) % 2 == 0) {
            faceNo =  sort ==0?"1":"2";
        } else {
            faceNo = sort ==0?"2":"1";
        }

        //找到固定列
        List<ArchiveCabinet> archiveCabinetList = archiveCabinetMapper.selectArchiveCabinetList(new ArchiveCabinet() {{
            setIsFixedCol("01");
            setArchiveAreaNo(arcBoxById.getAreaNo());
        }});
        //判空
        if (ObjectUtil.isEmpty(archiveCabinetList)) {
            throw new ServiceException("未查询到固定列信息，请检查重试！");
        }
        int controlLeftCode = Integer.parseInt(archiveCabinetList.get(0).getColNo());

        if (1 != controlLeftCode) {
            controlLeftCode = controlLeftCode / 2;
        }

        String area = "";
        // 左区
        if ((sort == 0 && columnNo < controlLeftCode) || (sort == 1 && columnNo > controlLeftCode)) {
            area = "left";
            // 右区
        } else if ((sort == 0 && columnNo > controlLeftCode) || (sort == 1 && columnNo < controlLeftCode)) {
            area = "right";
        } else if (columnNo == controlLeftCode) {
            if ("1".equals(faceNo)) {
                area = "left";
            } else if ("2".equals(faceNo)) {
                area = "right";
            } else {
                area = "right";
            }
        }

        if (arcBox.getType().equals("open")) {
            shelvesManager.open(ip, warehouseCode, areaCode, area, faceNo, columnNo, null);
        } else if (arcBox.getType().equals("close")) {
            shelvesManager.close(ip, warehouseCode, areaCode, area, null);
        } else if (arcBox.getType().equals("stop")) {
            shelvesManager.stop(ip, warehouseCode, areaCode, area, null);
        } else if (arcBox.getType().equals("unlock")) {
            shelvesManager.unlock(ip, warehouseCode, areaCode, area, null);
        }
        return 1;
    }
}
